#ifndef LCOM_LEVEL_H
#define LCOM_LEVEL_H

#include <utypes.h>
#include "window.h"

/** Altura de uma célula do nível */
#define LEVEL_CELL_HEIGHT 32

/** Largura de uma célula do nível */
#define LEVEL_CELL_WIDTH 40

/** Célula */
typedef unsigned char LevelCell;

/** Flags que descrevem uma célula do nível */
enum CellFlags {
	LEVEL_ALEXK   = (1<<0), /**< Alex Kidd */
	LEVEL_BLOCK   = (1<<1), /**< Bloqueia o movimento */
	LEVEL_DEATH   = (1<<2), /**< Objecto que mata */ 
	LEVEL_ALIVE   = (1<<3), /**< Objecto vivo que pode ser destruído */
	LEVEL_FRAGILE = (1<<4), /**< Sprite que morre quando há colisão */
};

/** Parede */
#define LEVEL_WALL LEVEL_BLOCK

/** Espaço vazio */
#define LEVEL_EMPTY 0

/** Tipo usado para representar sprites presentes no nível. */
typedef struct LevelSprite_ *LevelSprite;

/** Assinatura das funções chamadas quando ocorrem eventos no nível
 * \param win Janela do sprite
 * \param data Dados associados ao sprite
 */
typedef void (* LevelSpriteCallBack) (Window win, void *data);

/** Carrega um nível
 *
 * \param file Ficheiro com o nível
 */
void level_load (const char *file);

/** Descarrega um nível
 */
void level_unload (void);

/** Grava um nível
 * \param file Nome do ficheiro
 * \return True se foi possível gravar o nível
 */
Bool level_save (const char *file);

/** Obtém os dados do nível carregado
 *
 * \param map_addr Endereço onde é armazenado o mapa do nível
 * \param width_addr Endereço onde é armazenado a largura do mapa
 * \param height_addr Endereço onde é armazenado a altura do mapa
 * \return true se houver um nível carregado
 */
Bool level_get (LevelCell ***map_addr, int *width_addr, int *height_addr);

/** Inicializa um sprite de nível
 *
 * \param ls Sprite de nível
 * \param win Janela do sprite
 * \param killed Função chamada quando o sprite morre
 * \param unload Função chamada quando o mapa é descarregado que deve destruir os dados associados ao sprite
 * \param cell_w Largura da célula no sistema de coordenadas do ecrã
 * \param cell_h Altura da célula no sistema de coordenadas do ecrã
 * \param data Dados associados ao sprite
 */
void level_sprite_init (LevelSprite ls,
			Window win,
			LevelSpriteCallBack killed,
			LevelSpriteCallBack unload,
			int cell_w,
			int cell_h,
			void *data);

/** Activa flags do sprite
 *
 * \param ls Sprite de nível
 * \param flag Flag a ser activada
 */
void level_sprite_set_flag (LevelSprite ls, enum CellFlags flag);

/** Desactiva flags do sprite
 *
 * \param ls Sprite de nível
 * \param flag Flag a ser desactivada
 */
void level_sprite_unset_flag (LevelSprite ls, enum CellFlags flag);

/** Testa se uma posição no sistema de coordenadas do ecrã bloqueia movimentos
 *
 * \param x Coordenada x
 * \param y Coordenada y
 * \return Verdadeiro se bloqueia, false se o movimento é livre
 */
#define level_block_screen(x,y) level_block ((x) / xpm_level_cell_width, (y) / xpm_level_cell_height)

/** Testa se uma posição no sistema de coordenadas do mapa bloqueia movimentos
 *
 * \param x Coordenada x
 * \param y Coordenada y
 * \return Verdadeiro se bloqueia, false se o movimento é livre
 */
Bool level_block (int x, int y);

/** Faz a colisão entre sprites
 */
void level_collision (void);

/** Uma LevelSpriteCallBack que destroi a janela
 * \param win Janela do sprite
 * \param data Dados associados ao sprite
 */
void level_callback_delwin (Window win, void *data);


#endif /*LCOM_LEVEL_H*/


